package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.utils.StringUtils;

import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    Client client;
    @Autowired
    AliIoTConfigProperties aliIoTConfigProperties;
    @Autowired
    RedisTemplate<String,String> redisTemplate;
    @Autowired
    DeviceMapper deviceMapper;
    @Override
    public void syncProductList() {
        //请求参数
        QueryProductListRequest request = new QueryProductListRequest();
        //设置分页参数
        request.setPageSize(10);
        request.setCurrentPage(1);
        //设置实例id
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        //调用第三方查询产品接口
        QueryProductListResponse response;
        try {
            response = client.queryProductList(request);
        } catch (Exception e) {
            //物联网接口 - 查询产品，调用失败
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //判断,如果数据为空,则中断请求
        if (ObjectUtil.isEmpty(response.getBody())){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //获取数据,存储到redis
        List<ProductVo> productVoList = response.
                getBody().
                getData().
                getList().
                getProductInfo().
                stream().
                map(p -> BeanUtil.toBean(p, ProductVo.class))
                .collect(Collectors.toList());
        //存储到redis
        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY,  JSONUtil.toJsonStr(productVoList));
    }

    @Override
    public List<ProductVo> allProduct() {
        //从缓存中获取数据
        String jsonStr = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);

        //如果为空返回空集合
        if (StringUtils.isEmpty(jsonStr)){
            return Collections.emptyList();
        }

        return JSONUtil.toList(jsonStr, ProductVo.class);
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //校验设备名称是否重复
       Long count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
       if (count>0){
           throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
       }
       //iot新增设备
        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response=null;
        try {
            response = client.registerDevice(request);
        } catch (Exception e) {
            //物联网接口 - 注册设备，调用失败
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        //接口是否调通
        if (response==null|| !response.getBody().success){
            //物联网接口 - 注册设备，调用失败
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        //属性拷贝
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(response.getBody().getData().getIotId());
        log.info("设备注册成功，设备信息：{}",device);
        //产品名称
        device.setIotId(response.getBody().getData().getIotId());
        //查询IOT平台产品信息的信息--获得产品的名字
        QueryProductRequest productRequest = new QueryProductRequest();
        //设置公共实例的id
        productRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        //设置产品的key
        productRequest.setProductKey(deviceDto.getProductKey());
        //发送查询产品的请求
        QueryProductResponse queryProductResponse =null;
        try {
            queryProductResponse = client.queryProduct(productRequest);
        } catch (Exception e) {
          //注册设备失败,抛出异常
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //判断接口是否返回数据
        if (queryProductResponse.getBody().success){
           device.setProductName(queryProductResponse.getBody().getData().getProductName());
        }
        //如果位置是0,说明是随身设备,那么久应该设置物理位置为-1;
        if (device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }
        //保存到数据库
        try {
            deviceMapper.insert(device);
        } catch (Exception e) {
            //发起网络请求,删除IoT远程的设备
            log.error("保存设备信息到数据库失败,删除IOT远程设备{}",e.getMessage() );
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteDeviceRequest.setProductKey(deviceDto.getProductKey());
            deleteDeviceRequest.setDeviceName(deviceDto.getDeviceName());
            deleteDeviceRequest.setIotId(response.getBody().getData().getIotId());
            //client发起删除产品的请求
            DeleteDeviceResponse deleteDeviceResponse = null;
            try {
                deleteDeviceResponse =client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
                log.error("删除IOT远程设备失败");
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
            //老人已绑定此产品,请重新选择
            throw new BaseException(BasicEnum.RE_SELECT_PRODUCT);
        }
    }

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());
        Page<Device> devicePage =deviceMapper.pageQueryDevice(devicePageQueryDto);
        return PageResponse.of(devicePage, DeviceVo.class);
    }

    @Override
    public DeviceVo queryDeviceDetail(QueryDeviceDetailRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse response = null;
        try {
            response = client.queryDeviceDetail(request);
        }catch (Exception e){
            // 物联网接口 - 查询设备详情，调用失败
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //判断接口是否调通
        if (response==null||!response.getBody().success){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        DeviceVo deviceVo =deviceMapper.selectByIotId(response.getBody().getData().getIotId());
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();
        BeanUtil.copyProperties(data,deviceVo, CopyOptions.create().ignoreNullValue());
        return deviceVo;
    }

    @Override
    public  QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData queryDevicePropertyStatus(
            QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse response;
        try {
            response=client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
           throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_SERVICE_DATA_ERROR);
        }
        return response.getBody().getData();
    }

    @Override
    public  QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response;
        try {
            response=client.queryThingModelPublished(request);
        }catch (Exception e){
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        return response.getBody().getData();
    }

    @Override
    public void deleteDevice(DeleteDeviceRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        DeleteDeviceResponse response;
        try {
            response=client.deleteDevice(request);
        }catch (Exception e){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        if (!response.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        deviceMapper.deleteByIotId(request.getIotId());
    }

}
